//
//  common.h
//  template4
//
//  Created by Xiaochen Lian on 5/14/12.
//  Copyright (c) 2012 University of California, Los Angeles. All rights reserved.
//

#ifndef template4_common_h
#define template4_common_h

#include "Angel/Angel.h"
#include "Shapes.h"

typedef Angel::vec4 color4;
typedef Angel::vec4 point4;
typedef Angel::vec3 point3;
typedef Angel::vec2 point2;

struct lighting_struct
{
    color4 ambient, diffuse, specular;
    GLfloat shininess;
};

struct physic_parameters
{
    vec4 force;
    vec4 torque;
};

struct aerodynamic_parameters
{
    double rho; // 0.5 * air density
    double x1, x3;
    
    double drag_coef(double theta)
    {
        return cos(2*theta+M_PI)+1;
    }
    
    double lift_coef(double theta)
    {
        if (theta < - M_PI/12)
            return x1;
        else if ( theta < 6*x3 / (M_PI*(0.5*x3-x1)) )
            return x1 + (0.5*x3-x1)*12/M_PI * (theta + M_PI/12);
        else 
            return x3;
    }
};

struct bird_prop
{
    double mass;                // bird mass
    double ctrX, ctrY, ctrZ;    // bird center of mass
    // more properties for birds here
};

struct bird_parameters
{
    int num_params;
    double u[11];      // array of 1 + 4 * 2 + 2 = 11
    // 0-seep 1-4 left, 5-8 right, 9-10 tail
    
    bird_parameters() {}
    
    bird_parameters(const bird_parameters &p)
    {
        memcpy(u, p.u, sizeof(double)*11);
    }
};

struct bird_dof
{
    // 17 degree of freedom
    // wing sweep
    // (left or right) shoulder(2), wrist(2)
    // tail bend, twist
    // trunk position, orientation
    
    double shoulder_sweep;
    
    double lshoulder_dihedral;
    double lshoulder_twist;
    double lwrist_bend;
    double lwrist_twist;
    double rshoulder_dihedral;    
    double rshoulder_twist;
    double rwrist_bend;
    double rwrist_twist;    
    double tail_bend;
    double tail_twist;
    
    double trunk_pos_x;
    double trunk_pos_y;
    double trunk_pos_z;
    
    double trunk_rot_x;
    double trunk_rot_y;
    double trunk_rot_z;
};

struct bird_status
{
    double shoulder_sweep[3];
    
    double lshoulder_dihedral[3];
    double lshoulder_twist[3];
    double lwrist_bend[3];
    double lwrist_twist[3];
    double rshoulder_dihedral[3];
    double rshoulder_twist[3];
    double rwrist_bend[3];
    double rwrist_twist[3];    
    double tail_bend[3];
    double tail_twist[3];
    
    point4 pos;
//    double posX, posY, posZ;  // bird position
//    double rotX, rotY, rotZ;  // bird orientation
        
    vec4 velocity;
//    double spdX, spdY, spdZ;  // bird speed
//    double aspX, aspY, aspZ;  // bird angular speed
  
    vec4 accelerate;
//    double pacX, pacY, pacZ;  // bird speed accelaration
//    double aacX, aacY, aacZ;  // bird angular accelartion
    
    bird_status() {}
    
    bird_status(const bird_status &status)
    {
        for (int i = 0; i < 3; ++i)
        {
            shoulder_sweep[i] = status.shoulder_sweep[i];
            
            lshoulder_dihedral[i] = status.lshoulder_dihedral[i];
            lshoulder_twist[i] = status.lshoulder_twist[i];
            lwrist_bend[i] = status.lwrist_bend[i];
            lwrist_twist[i] = status.lwrist_twist[i];
            
            rshoulder_dihedral[i] = status.rshoulder_dihedral[i];
            rshoulder_twist[i] = status.rshoulder_twist[i];
            rwrist_bend[i] = status.rwrist_bend[i];
            rwrist_twist[i] = status.rwrist_twist[i];
            
            tail_bend[i] = status.tail_bend[i];
            tail_twist[i] = status.tail_twist[i];
        }
        
        pos = status.pos;
        velocity = status.velocity;
        accelerate = status.accelerate;
    }
    
    void status_by_dof(double *status, double dof)
    {
        status[0] = status[1] + (status[2]-status[1]) * dof;
    }
};

extern aerodynamic_parameters aero_coef;

// Structs that hold the Vertex Array Object index and number of vertices of each shape.
extern ShapeData cubeData;
extern ShapeData sphereData;
extern ShapeData ellipsData;
extern ShapeData coneData;
extern ShapeData cylData;
extern ShapeData axisData;

extern mat4         model_view;
extern GLint        uModelView, uProjection, uCameraView;
extern GLint        uAmbient, uDiffuse, uSpecular, uLightPos, uShininess;
extern GLint        uTex, uEnableTex;
extern lighting_struct g_env_lighting;

extern GLuint program_axis;
extern GLint uModelView_axis, uProjection_axis, uCameraView_axis;

void drawAxis(mat4 model_view);
/////////////////////////////////////////////////////
//    PROC: drawCylinder()
//    DOES: this function 
//          render a solid cylinder  oriented along the Z axis. Both bases are of radius 1. 
//          The bases of the cylinder are placed at Z = 0, and at Z = 1.
//
//          
// Don't change.
//////////////////////////////////////////////////////
void drawCylinder(mat4 model_view);

//////////////////////////////////////////////////////
//    PROC: drawCone()
//    DOES: this function 
//          render a solid cone oriented along the Z axis with base radius 1. 
//          The base of the cone is placed at Z = 0, and the top at Z = 1. 
//         
// Don't change.
//////////////////////////////////////////////////////
void drawCone(mat4 model_view);

//////////////////////////////////////////////////////
//    PROC: drawCube()
//    DOES: this function draws a cube with dimensions 1,1,1
//          centered around the origin.
// 
// Don't change.
//////////////////////////////////////////////////////
void drawCube(mat4 model_view);

//////////////////////////////////////////////////////
//    PROC: drawSphere()
//    DOES: this function draws a sphere with radius 1
//          centered around the origin.
// 
// Don't change.
//////////////////////////////////////////////////////
void drawSphere(mat4 model_view);

void drawEllips(mat4 model_view);

//----------------------------------------------------------------------------
//
//  Translation Rotation matrix generators
//
mat4 TRTX( const GLfloat theta, const vec3 v );
mat4 TRTY( const GLfloat theta, const vec3 v );
mat4 TRTZ( const GLfloat theta, const vec3 v );
#endif
